package cn.edu.njust.balancer;

import cn.edu.njust.server.Server;
import cn.edu.njust.server.Stat;
import cn.edu.njust.strategy.LoadBalanceStrategy;
import cn.edu.njust.strategy.StatefulStrategy;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;

@Setter
@Getter
@Builder
public class DefaultLoadBalancer implements LoadBalancer {

    private List<Server> servers;

    private List<Stat> stats;

    private List<Integer> weights;

    private LoadBalanceStrategy strategy;

    public Server next() {
        return getServerProxy(strategy.next(stats, weights));
    }

    public void init() {
        if (servers == null)
            throw new RuntimeException("Not server list");

        if (weights == null) {
            weights = new ArrayList<>(servers.size());
            for (int i = 0; i < servers.size(); i++)
                weights.add(Integer.valueOf(1));
        }

        stats = new ArrayList<>(servers.size());
        for (int i = 0; i < servers.size(); i++)
            stats.add(new Stat());

        if (strategy instanceof StatefulStrategy)
            ((StatefulStrategy) strategy).init(stats, weights);
    }

    private void onServerListChange() {
        if (strategy instanceof StatefulStrategy)
            ((StatefulStrategy) strategy).reorg(stats, weights);
    }

    /**
     * 利用JDK动态代理，产生服务器对象的代理对象，用于监控服务链路信息
     * @param index
     * @return
     */
    protected Server getServerProxy(int index) {
        Server server = servers.get(index);
        Stat stat = stats.get(index);

        return (Server) Proxy.newProxyInstance(
                server.getClass().getClassLoader(),
                new Class[]{Server.class},
                new ServerStatUpdaterProxyHandler(server, stat)
        );
    }
}
